/**
 * 
 */
package org.yelongframework.model.support.mybatis.mapping.result;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.mapping.ResultFlag;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.apache.ibatis.type.UnknownTypeHandler;
import org.yelongframework.commons.lang.EnumUtil;
import org.yelongframework.model.manager.FieldAndColumn;
import org.yelongframework.model.manager.FieldAndColumnType;
import org.yelongframework.model.manager.ModelAndTable;

/**
 * 结果映射构建器默认实现
 * 
 * @since 1.0.0
 */
public class DefaultResultMappingBuilder implements ResultMappingBuilder {

	// ==================================================构建结果映射==================================================

	@Override
	public List<ResultMapping> build(ModelAndTable modelAndTable, Configuration configuration) {
		List<ResultMapping> resultMappings = new ArrayList<>();
		modelAndTable.getFieldAndColumnsByType(FieldAndColumnType.ORDINARY, FieldAndColumnType.PRIMARYKEY,
				FieldAndColumnType.EXTEND).stream().filter(FieldAndColumn::isSelect).forEach(x -> {
					List<ResultFlag> flags = new ArrayList<>();
					// String columnName = x.getColumn();
					String selectColumnName = x.getSelectColumn();
					String propertyName = x.getFieldName();
					String nestedResultMapId = null;
					if (x.isPrimaryKey()) {
						flags.add(ResultFlag.ID);
					}
					TypeHandler<?> typeHandler = resolveTypeHandler(x.getFieldType(), null, configuration);
					String jdbcTypeStr = x.getJdbcType();
					JdbcType jdbcType = StringUtils.isEmpty(jdbcTypeStr) ? null
							: EnumUtil.valueOf(JdbcType.class, jdbcTypeStr);// 如果jdbcType没有映射的枚举则返回null
					ResultMapping resultMapping = new ResultMapping.Builder(configuration, propertyName,
							selectColumnName, x.getFieldType()).flags(flags).jdbcType(jdbcType)
									.nestedResultMapId(nestedResultMapId).typeHandler(typeHandler).build();
					resultMappings.add(resultMapping);
				});
		return resultMappings;
	}

	// ==================================================解析类型处理器==================================================

	/**
	 * 解析类型处理器
	 * 
	 * @param javaType        Java类型
	 * @param typeHandlerType 类型处理器类型
	 * @param configuration   配置
	 * @return 类型处理器
	 */
	protected TypeHandler<?> resolveTypeHandler(Class<?> javaType, Class<? extends TypeHandler<?>> typeHandlerType,
			Configuration configuration) {
		if (null == typeHandlerType || typeHandlerType == UnknownTypeHandler.class) {
			return null;
		}
		TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
		TypeHandler<?> handler = typeHandlerRegistry.getMappingTypeHandler(typeHandlerType);
		if (null == handler) {
			handler = typeHandlerRegistry.getInstance(javaType, typeHandlerType);
		}
		return handler;
	}

}
